{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import glob\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "import time"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 将日度回报率的excel文件合并"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "#file_list=[i for i in glob.iglob(r\"C:\\Users\\lenovo\\Desktop\\日个股回报\\*.xlsx\")]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "#Daily_return = pd.DataFrame()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#df = pd.read_excel('12.xlsx')\n",
    "#df = df.drop(index=[0,1], axis=0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {},
   "outputs": [],
   "source": [
    "#Daily_return = pd.concat([Daily_return,df], axis=0)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 数据预处理"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "'''\n",
    "剔除异常数据\n",
    "Daily_return = Daily_return.sort_values(by='Dretwd',ascending=True)\n",
    "Daily_return = Daily_return.drop(Daily_return.index[0:101], axis=0) # 剔除异常值101个(ret<-0.2)\n",
    "Daily_return = Daily_return.sort_values(by='Dretwd',ascending=False)\n",
    "Daily_return = Daily_return.drop(Daily_return.index[0:3258], axis=0) # 剔除异常值3258个(ret>0.2)\n",
    "Daily_return = Daily_return.sort_values(by=['Stkcd','Trddt']) # 按['Stkcd','Trddt']进行排序\n",
    "Daily_return.to_csv('Daily_return.csv')\n",
    "'''"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "Daily_return = pd.read_csv('Daily_return.csv')\n",
    "Daily_return = Daily_return.drop(['Unnamed: 0','Unnamed: 0.1','Dretnd'], axis=1)\n",
    "Daily_return.index = Daily_return['Stkcd']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 175,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 获取股票代码\n",
    "#Stock_code_array = np.array(Daily_return['Stkcd'].drop_duplicates())\n",
    "#Stock_code = Stock_code_array.tolist()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 获取交易月份数据\n",
    "trade_date = np.array(Daily_return['Trddt'].drop_duplicates()) # 将\"Trddt\"这列数据提取，剔除重复值，转换为array\n",
    "date_list = []                                              # 设置个空列表，仅保留交易日期的年月，赋值到空列表中\n",
    "for j in range(0,len(trade_date)):\n",
    "        date = trade_date[j][0:7]\n",
    "        date_list.append(date)\n",
    "df_date = pd.DataFrame(date_list)                           # 将交易日期列表转换为dataframe\n",
    "df_date.rename(columns={0:\"trade_month\"},inplace=True)      # 将列名设置为trade_month\n",
    "df_date = df_date.drop_duplicates()                         # 将重复的交易日期删除\n",
    "df_date = df_date.sort_values(by='trade_month',ascending=True) # 按照日期顺序排列整齐\n",
    "list_month = df_date['trade_month'].tolist()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Minutes taken = 0.08579005400339762\n"
     ]
    }
   ],
   "source": [
    "# 将Daily_return的index修改为只保留年份和月份的交易日期\n",
    "trade_date = np.array(Daily_return['Trddt'])                # 将\"Trddt\"这列数据提取，转换为array\n",
    "date_list = []                                              # 设置个空列表，仅保留交易日期的年月，赋值到空列表中\n",
    "tic = time.time()\n",
    "for j in range(0,len(trade_date)):\n",
    "        date = trade_date[j][0:7]\n",
    "        date_list.append(date)\n",
    "df_date = pd.DataFrame(date_list)                           # 将交易日期列表转换为dataframe\n",
    "df_date.rename(columns={0:\"trade_month\"},inplace=True)      # 将列名设置为trade_month\n",
    "df_date = df_date                                           # 将重复的交易日期删除\n",
    "trade_month_list = df_date['trade_month'].tolist()\n",
    "Daily_return.index = trade_month_list\n",
    "toc = time.time()\n",
    "print(\"Minutes taken = \" + str((toc-tic)/60.0))   "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 将股票代码前缺失的0补齐新生成一列数据，并替换原来的\"Stkcd\"\n",
    "stock_code_array = np.array(Daily_return['Stkcd']) # 提取每个月在交易的股票代码，将其先转换成array\n",
    "stock_code = stock_code_array.tolist() # 而后将array转换成list\n",
    "stk_code = [] \n",
    "for i in stock_code:\n",
    "    code = str(i).zfill(6)\n",
    "    stk_code.append(code)\n",
    "Daily_return['Stkcd'] = stk_code"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 获取每个月股票的日度最大收益率的List数据（N=1）--Table 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Goal:设置一个大的list,将每个月所有股票的最大收益率设置成小dataframe，放入大list中，方便后面进行索引\n",
    "Max_DailyReturn = [] \n",
    "tic = time.time()\n",
    "# Step1:提取每个月所有股票的日度收益率\n",
    "for i in list_month:\n",
    "    print(i)\n",
    "    month_data = Daily_return.loc[i]                             \n",
    "    code_array = np.array(month_data['Stkcd'].drop_duplicates()) # 提取每个月在交易的股票代码，将其先转换成array\n",
    "    code = code_array.tolist()                                   # 将array转换成list\n",
    "    month_data.index = month_data['Stkcd']                       # 将index修改为股票代码    \n",
    "    month_data = month_data.drop(['Stkcd','Trddt'], axis=1)      # 删除\"Stkcd\"和\"Trddt\"两列数据\n",
    "    #Step2: 提取每只股票在该月的日度收益率数据，并提取最大值\n",
    "    max_DailyReturn = []\n",
    "    for j in code:\n",
    "        max_ret = month_data.loc[j]['Dretwd'].max()     \n",
    "        max_DailyReturn.append(max_ret)\n",
    "    #Step3: 将每只股票每月最大的日度收益率数据生成小dataframe\n",
    "    max_DailyReturn = pd.DataFrame(max_DailyReturn)     \n",
    "    max_DailyReturn.index = code                             \n",
    "    max_DailyReturn.rename(columns={0:\"max_ret\"},inplace=True)\n",
    "    #Step4: 将每个月的股票最大收益率的dateframe放入大list中\n",
    "    Max_DailyReturn.append(max_DailyReturn)            \n",
    "toc = time.time()\n",
    "print(\"Minutes taken = \" + str((toc-tic)/60.0))    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "#将个股最大日收益率数据提取出来\n",
    "Max_ret = pd.DataFrame()\n",
    "for i in range(0,len(Max_DailyReturn)):\n",
    "    data = Max_DailyReturn[i]\n",
    "    data['Group'] = (i+1)*np.ones(len(data))\n",
    "    Max_ret = pd.concat([Max_ret,data], axis=0)\n",
    "Max_ret.to_excel('Max_daily_return.xlsx')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 提取MAX因子，MAX（-1）因子，并进行merge"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "MAX = Max_ret[~Max_ret['Group'].isin([1])] # 提取MAX因子\n",
    "MAX_1 = Max_ret[~Max_ret['Group'].isin([252])] # 提取MAX_1因子，即滞后一期的MAX\n",
    "MAX['Group'] = MAX['Group']-1  # 将MAX的月份修改为从1开始，方便两个因子的合并\n",
    "MAX['Stk'] = MAX.index  # 填充一列'Stk'数据\n",
    "MAX_1['Stk'] = MAX_1.index  # 填充一列'Stk'数据\n",
    "Factor_set = pd.merge(MAX,MAX_1,on=['Group','Stk']) # 以\"Group\",\"Stk\"这两个key进行合并，会将多余数据剔除"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 156,
   "metadata": {},
   "outputs": [],
   "source": [
    "Factor_set.to_excel('Fac_MAX.xlsx')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 获取每个月股票的平均N日最大收益率的List数据（N=2,3,4,5）--Table 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Goal:设置一个大的list,将每个月所有股票的最大收益率设置成小dataframe，放入大list中，方便后面进行索引\n",
    "N = 5\n",
    "Average_max_ret = [] \n",
    "tic = time.time()\n",
    "# Step1:提取每个月所有股票的日度收益率\n",
    "for i in list_month:\n",
    "    print(i)\n",
    "    month_data = Daily_return.loc[i]                             \n",
    "    code_array = np.array(month_data['Stkcd'].drop_duplicates()) # 提取每个月在交易的股票代码，将其先转换成array\n",
    "    code = code_array.tolist()                                   # 将array转换成list\n",
    "    month_data.index = month_data['Stkcd']                       # 将index修改为股票代码    \n",
    "    month_data = month_data.drop(['Stkcd','Trddt'], axis=1)      # 删除\"Stkcd\"和\"Trddt\"两列数据\n",
    "    #Step2: 提取每只股票在该月的日度收益率数据，降序排列，取N=2,3,4,5个数据，并求均值\n",
    "    average_max_ret = []\n",
    "    for j in range(0,len(code)):\n",
    "        df = month_data.loc[code[j]]   # 提取个股的在当月的日度收益率数据\n",
    "        df.index = [df['Dretwd'].tolist()]  # 将df的index修改为\"Dretwd\"列值\n",
    "        stk_ret = df.sort_index(ascending=False).iloc[0:N]  # 降序排列，并取N个数据\n",
    "        aver_ret = np.mean(list(stk_ret.index))  # 求N个最大值数据的平均值\n",
    "        average_max_ret.append(aver_ret)   # 平均值放入average_max_ret中\n",
    "    #Step3: 将每只股票每月最大的日度收益率数据生成小dataframe\n",
    "    average_max_ret = pd.DataFrame(average_max_ret)     \n",
    "    average_max_ret.index = code                             \n",
    "    average_max_ret.rename(columns={0:\"max_ret\"},inplace=True)\n",
    "    #Step4: 将每个月的股票最大收益率的dateframe放入大list中\n",
    "    Average_max_ret.append(average_max_ret)            \n",
    "toc = time.time()\n",
    "print(\"Minutes taken = \" + str((toc-tic)/60.0))    "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 按照上个月一日最大日度收益率从小到大对股票进行分组"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 157,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Minutes taken = 0.23697441418965656\n"
     ]
    }
   ],
   "source": [
    "### Goal: 每个月分10组数据，先设置个大List包含全部月份的总数据，大List中的元素list即每个月份的分组\n",
    "All_group = []\n",
    "tic = time.time()\n",
    "for i in range(0,len(list_month)):\n",
    "    # Step1: 提取每个月份的最大日收益率数据并进行升序，给Table2分组时，在此处修改\n",
    "    max_daily_return =  Max_DailyReturn[i].sort_values(by='max_ret',ascending=True) \n",
    "    quantile = len(max_daily_return) // 10     # 设置分位点\n",
    "    # Step2: 按照分位点将股票分成10组，并放入小list中\n",
    "    Group = []\n",
    "    for i in range(0,10):\n",
    "        if i <= 8:\n",
    "            group = max_daily_return.iloc[i*quantile : (i+1)*quantile]\n",
    "        else:\n",
    "            group = max_daily_return.iloc[9*quantile : ]\n",
    "        Group.append(group)\n",
    "    # Step3: 将每个月的股票分组放入大List中\n",
    "    All_group.append(Group)\n",
    "toc = time.time()\n",
    "print(\"Minutes taken = \" + str((toc-tic)/60.0))    "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 计算每个投资组合的时序上的等权重以及市值加权收益率"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 167,
   "metadata": {},
   "outputs": [],
   "source": [
    "month_return = pd.read_csv('TRD_Mnth.csv')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 169,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 将股票代码前缺失的0补齐新生成一列数据，并替换原来的\"Stkcd\"\n",
    "stock_code_array = np.array(month_return['Stkcd']) # 提取每个月在交易的股票代码，将其先转换成array\n",
    "stock_code = stock_code_array.tolist() # 而后将array转换成list\n",
    "stk_code = [] \n",
    "for i in stock_code:\n",
    "    code = str(i).zfill(6)\n",
    "    stk_code.append(code)\n",
    "month_return['Stkcd'] = stk_code"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 170,
   "metadata": {},
   "outputs": [],
   "source": [
    "month_return.index = month_return['Trdmnt'] # 将index替换成交易日期\n",
    "month_return = month_return.fillna(0)   # 将空值填充为0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 199,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Minutes taken = 1.3870155413945515\n"
     ]
    }
   ],
   "source": [
    "# Goal: 获取每个股票组合在时间序列上的月度收益率\n",
    "# Step1: 提取股票组合在时间序列上的收益率数据\n",
    "Group_VW = []\n",
    "Group_EW = []\n",
    "tic = time.time()\n",
    "for j in range(0,10):\n",
    "    group_vw = []\n",
    "    group_ew = []\n",
    "    for i in range(0,len(list_month)-1):\n",
    "        group_code = All_group[i][j].index # 提取股票组合在上月的股票代码\n",
    "        group_code = list(group_code)\n",
    "        mth_ret = month_return.loc[list_month[i+1]]   # 提取当月的股票月度回报率\n",
    "        mth_ret.index = mth_ret['Stkcd']  # 现在已与时间无关，将index更换为\"Stkcd\"\n",
    "        mth_ret = mth_ret.drop(['Stkcd','Trdmnt','Volume'], axis=1) # 删除'Stkcd','Trdmnt','Volume'三列数据\n",
    "# Specical Step: 由于上月正常交易的股票，在当月可能发生停牌，当stock in group_code and not in mth_ret.index时,\n",
    "#  group = mth_ret.loc[group_code] 索引会报错，故先执行如下操作，将存在异常交易的股票剔除\n",
    "        drop = []\n",
    "        for k in group_code:\n",
    "            if k not in mth_ret.index:\n",
    "                drop.append(k)\n",
    "            else:None\n",
    "        for m in drop:\n",
    "            group_code.remove(m)\n",
    "        group = mth_ret.loc[group_code]  # 提取股票组合的数据\n",
    "# Step2: 计算股票组合在时序上的组合收益率，并将其放入小list中\n",
    "        Total_value = np.array(group['Market_value']).sum() # 计算该组股票当月的总市值\n",
    "        group['Weight'] = np.array(group['Market_value']) / Total_value # 计算该组股票的市值权重，并赋值给\"Weight\"\n",
    "        VW = (np.array(group['Weight']) * np.array(group['Month_ret'])).sum()*100 # 计算市值加权收益率\n",
    "        VW = np.around(VW,2) # 保留两位小数点\n",
    "        EW = (np.array(group['Month_ret']) / len(group)).sum()*100 # 计算等权重收益率\n",
    "        EW = np.around(EW,2) \n",
    "        group_vw.append(VW)\n",
    "        group_ew.append(EW)\n",
    "# Step3; 重复上述步骤，将每个股票组合在时序上收益率的list放入大List中\n",
    "    Group_VW.append(group_vw)\n",
    "    Group_EW.append(group_ew)\n",
    "toc = time.time()\n",
    "print(\"Minutes taken = \" + str((toc-tic)/60.0))    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 196,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Minutes taken = 1.4456402937571207\n"
     ]
    }
   ],
   "source": [
    "'''\n",
    "方案2\n",
    "# Goal: 获取每个股票组合在时间序列上的月度收益率\n",
    "# Step1: 提取股票组合在时间序列上的收益率数据\n",
    "Group_VW = []\n",
    "Group_EW = []\n",
    "tic = time.time()\n",
    "for j in range(0,10):\n",
    "    group_vw = []\n",
    "    group_ew = []\n",
    "    for i in range(0,len(list_month)-1):\n",
    "        group = All_group[i][j] # 提取股票组合在上月的股票代码\n",
    "        group['Stkcd'] = group.index\n",
    "        mth_ret = month_return.loc[list_month[i+1]]   # 提取当月的股票月度回报率\n",
    "        mth_ret = mth_ret.drop(['Trdmnt','Volume'], axis=1)\n",
    "        Df = pd.merge(group,mth_ret,on='Stkcd')\n",
    "# Specical Step: 由于上月正常交易的股票，在当月可能发生停牌，当stock in group_code and not in mth_ret.index时,\n",
    "#  group = mth_ret.loc[group_code] 索引会报错，故先执行如下操作，将存在异常交易的股票剔除\n",
    "# Step2: 计算股票组合在时序上的组合收益率，并将其放入小list中\n",
    "        Total_value = np.array(Df['Market_value']).sum()\n",
    "        Df['Weight'] = np.array(Df['Market_value']) / Total_value \n",
    "        VW = (np.array(Df['Weight']) * np.array(Df['Month_ret'])).sum()*100 # 计算市值加权收益率\n",
    "        VW = np.around(VW,2) # 保留两位小数点\n",
    "        EW = (np.array(Df['Month_ret']) / len(group)).sum()*100 # 计算等权重收益率\n",
    "        EW = np.around(EW,2)\n",
    "        group_vw.append(VW)\n",
    "        group_ew.append(EW)\n",
    "# Step3; 重复上述步骤，将每个股票组合在时序上收益率的list放入大List中\n",
    "    Group_VW.append(group_vw)\n",
    "    Group_EW.append(group_ew)\n",
    "toc = time.time()\n",
    "print(\"Minutes taken = \" + str((toc-tic)/60.0))    \n",
    "'''"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 197,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 将时间序列上的VW_Protfolio数据保存下来\n",
    "Df_Group_VW = pd.DataFrame(Group_VW)\n",
    "Df_Group_VW  = Df_Group_VW.T \n",
    "Df_Group_VW.to_excel('Group_VW.xlsx')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 198,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 将时间序列上的EW_Protfolio数据保存下来\n",
    "Df_Group_EW = pd.DataFrame(Group_EW)\n",
    "Df_Group_EW  = Df_Group_EW.T \n",
    "Df_Group_EW.to_excel('Group_EW.xlsx')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 计算每个股票组合的Average Max"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 193,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Step1: 提取每个股票组合在时序上的数据\n",
    "Average_Max = []\n",
    "for i in range(0,10):\n",
    "    max_ret = []\n",
    "    # Step2: 在时序上，提取每个股票组合中最大的个股收益率\n",
    "    for j in range(0,len(All_group)):\n",
    "        group_data = All_group[j][i]['max_ret']\n",
    "        group_data_array = np.array(group_data)\n",
    "        max_ret.append(group_data_array[-1])\n",
    "    # Step3: 计算每个股票组合的 Average Max 并append到List中\n",
    "    average_max = np.mean(max_ret)*100\n",
    "    Average_Max.append(np.around(average_max,2))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 将待回归数据整理成适合statsby分组回归的数据格式"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 241,
   "metadata": {},
   "outputs": [],
   "source": [
    "data = pd.read_excel('10-1_reg.xlsx')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 209,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 计算group_1 ~ group_10 的超额收益率，并添加到dataframe中\n",
    "for i in range(1,11):\n",
    "    data['ret_'+ str(i)] = data['group_' + str(i)] - data['rf']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 210,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 删除group_1 ~ group_10 的收益率数据\n",
    "for i in range(1,11):\n",
    "    data = data.drop(columns = ['group_'+ str(i)], axis=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 243,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Step1: 创建一个与data_array格式一致的array\n",
    "statsby = np.zeros(shape=(251,7))\n",
    "# Step2: 将各个组的时间序列数据进行纵向合并\n",
    "for i in range(1,9): #### 针对不同Table，记得调整range！！！\n",
    "    data_array = np.array(data.loc[:,['month','ret_'+str(i),'mkt_rf','smb','hml','umd','name_'+str(i)]])\n",
    "    statsby = np.concatenate((statsby,data_array), axis=0)\n",
    "# Step3: 将array转换成dataframe，\n",
    "Df = pd.DataFrame(statsby)\n",
    "Df = Df.drop(Df.index[0:251], axis=0) # 剔除多余数据\n",
    "Df.columns = ['month', 'ex_ret', 'mkt_rf','smb','hml','umd','Group'] # 修改列名"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 245,
   "metadata": {},
   "outputs": [],
   "source": [
    "Df.to_excel('10-1_stata.xlsx')"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
